Intro informal

Todos sabemos que está bueno descomponer en módulos, pero cómo?
Esa es la gran pregunta.

Parnas nos da un ejemplito simple de algo a resolver y dos
descomposiciones posibles.

La primera es la que llama standard, y la segunda es la que el propone
que se utilice.

En la primera se descompone siguiendo el data-flow.
En la segunda la descomposición se basa en el ocultamiento de 
información, las decisiones importantes quedan restringidas a cada
módulo.

Dice bueno, la primera es la que todos conocemos, buenísimo, ahora que
tal esta descomposición nueva.
Parece extraña al principio y puede traer overhead, y hay que tener
cuidado al aplicarla.

Se comparan las dos descomposiciones respecto a varios aspectos, y se
concluye que la segunda es mucho más modificable, que los cambios
quedan restringidos a un módulo y que no afectan a todo el sistema.
Las decisiones quedan encapsuladas.

Es importante porque luego este concepto de information hiding (que el
no usa con este nombre) sera muy importante para la programación 
orientada a objetos.


------------------------------------------------------------------------

La modularización se enfoca como un mecanismo para mejorar la 
flexibilidad y la comprensión de un sistema, así como también para
acortar el tiempo de desarrollo.
La eficiencia de la modularización depende de los criterios usados 
en la descomposición.
Se presente un problema de diseño y se describen descomposiciones,
una convencional y otra no convencional.
Se muestra que la descomposición no convencional tiene claras ventajas,
teniendo en cuenta los objetivos expuestos.
Se discuten los criterios usados para la descomposición.
Si se sigue el supuesto de que los módulos están compuestos por una o
más subrutinas, la implementación de la descomposición no
tradicional será menos efectiva.
Sin embargo, existe un enfoque alternativo para la implementación
que se dan esbozos.


La programación modular permite
    -escribir un módulo con poco conocimiento del código de otro módulo
    (independencia, encapsulación)
    -reensamblar y reemplazar módulos sin necesidad de cambiar todo
    el sistema (bajo acoplamiento)
    

Beneficios de la programación modular
    -el tiempo de desarrollo puede acortarse porque se puede paralelizar
    el trabajo. Distintos grupos trabajan en distintos módulos sin 
    necesidad de estar comunicándose seguido.
    -el producto es más flexible. Debería ser posible realizar cambios
    drásticos a un módulo sin tener que cambiar el resto.
    -el sistema es más comprensible. Debería ser posible estudiar el
    sistema de a un módulo a la vez.
    El sistema se puede diseñar mejor porque se entiende más.
    

módulo: asignación de responsabilidad (y no necesariamente un 
subprograma).


Sistema que propone de ejemplo de sistema, el kwic index, que 
acepta un conjunto ordenado de líneas, donde cada una es un conjunto 
ordenado de palabras, y cada palabra un conjunto ordenado de caracteres.
Cada línea puede ser shifteada circularmente.
El kwic index da como resultado una lista de todos los shifts 
circulares de todas las líneas en orden alfabético.

(Nos dan líneas y tenemos que devolver todos los shifts circulares de 
ellas en orden alfabético).

Es un sistema chico, con poca complejidad en que las cuestiones que
motivan la descomposición en módulos no sin importantes, pero es
util usarlo para ver cómo sería, ya que es muy poco práctico explicar
la descomposición en un sistema grande.


Modularización 1
Módulos
    Input
    Shift Circular
    Alfabetizador
    Output
    Control
    
El sistema se divide en un número de módulos con interfaces bien
definidas. Cada módulo es lo suficientemente chico y simple para
poder ser entendido en su totalidad y para ser bien programado.
Hay experimentos que indican que esta es la descomposición más elegida.



Modularización 2
Módulos
    Lineas
        ver caracteres y setearlos
        ver cantidad de palabras en una linea
        borrar partes de líneas
    Input
    Shirt Circular
        similares a lo de las líneas
    Alfabetizador
    Output
    Control
    

Comparación

General

Ambas funcionan, la primera descomposición es más convencional, y la
se usa a veces como proyecto de clases (?).
Ambas reducen la programación del sistema a la relativamente
independiente programación de un números de programas chicos y 
manejables (los módulos).

Las diferencias están en la manera en que se divide el trabajo, y en
las interfaces entre los módulos.
%Los algoritmos pueden ser los mismos.

Los sistemas son sustancialmente diferentes aunque sea idénticos en
tiempo de ejecución.


Modificabilidad

Hay decisiones de diseño que son cuestionables o que pueden cambiar 
bajo ciertas circunstancias.
Esta es una lista parcial

1. Formato de input.
2. La decisión de tener todas las líneas almacenadas en memoria. Para
trabajos grandes esto puede resultar poco conveniente o poco práctico.
3. La decisión de empaquetar los caracteres four to word 
%no entendiestos
Si estamos trabajando con pocos datos, no es deseable empaquetar, ya
que es mucho mejor tener una distribución de un caracter por palabra.
4. La decisión de tener un índice para el shift circular, en vez de 
guardar los shifts directamente. 
Para casos chicos, escribirlos puede ser el enfoque preferible.
5. La decisión de alfabetizar la lista una vez, y no hacer
a) buscar un item cuando se necesita
b) alfabetizar parcialmente.
En algunas circunstancias puede ser ventajoso distribuir el cómputo
involucrado en la alfabetización en el tiempo requerido para producir
el índice.

Mirando estos cambios pueden verse las diferencias entre los módulos.

En la primera descomposición estos cambios impactan más.

Para ambas descomposiciones la decisión del formato del input está
reducida a un solo módulo.

Para la primera descomposición la decisión de donde tener almacenadas
las líneas impacta en todos los modulos. Pasa lo mismo para otros
cambios.
Por otro lado, en la segunda descomposición pasan cosas totalmente
distintas, los cambios impactan en un solo módulo, ya que ocultan
estas decisiones a los demás.


Desarrollo Independiente

En la primera descomposición, las interfaces entre los módulos son
específicas, se pasan tablas con formatos bastante complejos.
En la segunda, las interfaces son más abstractas, consisten mayormente
en los nombres de las funciones y sus aridades.


Comprensión

En la primera descomposición, para entender el módulo del output
también es necesario conocer un poco como funciona el alfabetizador,
el shift circular, y el input.
Hay aspectos de las tablas que usa el módulo del output que solo
tienen sentido porque otros módulos funcionan de la forma en la que
lo hacen. Hay restricciones en las estructuras de las tablas por los
algoritmos que se usan en los otros módulos.

Se supone que en la segunda descomposición es mucho más facil
comprender un módulo sin tener que ver a los otros.



Criterios usados para la descomposición

En la primera, el criterio fue hacer que cada etapa del procesamiento
fuera un módulo. Se puede decir que se hace un flowchart.

En la segunda, el criterio fue el ocultamiento de la información. Los
módulos ya no se corresponden necesariamente con etapas del 
procesamiento. Cada módulo se caracteriza por su conocimiento de una
decisión de diseño que oculta a todos los demás. Su interfaz fue
elegida para revelar lo menos posible de cómo funciona internamente.


%Mejoras posibles
%NO


%Mas consejos

Además del criterio general de que cada módulo esconda decisiones de
diseño del resto del sistema, se mencionan ejemplos específicos que
parecen recomendables.

1. Una estructura de datos, y la forma de accederla y modificarla deben
ser parte de un mismo módulo.

2. La secuencia de instrucciones necesarias para llamar a una rutina
específica, y la propia rutina deben ser parte de un mismo módulo.

%3. El formato de los bloques de control debe ser ocultado dentro de 
%un módulo dedicado.

4. Los códigos de caracteres y los órdenes alfabéticos deben ser
ocultos en un módulo para ganar flexibilidad.


Eficiencia e Implementación

Si no se tiene cuidado, al usar la segunda descomposición puede pasar
que la performance sea mucho peor que usar la primera.

Si cada una de las funciones se implementa como un procedimiento con
una secuencia elaborada para llamarla, habrá mucho overhead por el
frecuente intercambio entre módulos.

Entonces, la implementación debe hacerse una una forma no tradicional.
% bla bla bla


Una descomposición comun a un compilador e intérprete para un mismo lenguaje

Existen problemas similares cuando se compila que cuando se interpreta.
Hay pocos cambios.
El orden en que cada procesamiento se espera que ocurra, no debe usarse
para descomponer en módulos. 
%no pensar en como va a ser ejecutado
Un trabajo de descomposición cuidadoso puede dar sus frutos, al permitir
que muchas cosas se mantengan al cambiar de proyecto.


Estructura Jerárquica

El sistema permite tener una sola representación para programas que
pueden correr en dos niveles jerárquicos.
En las discusiones de las estructuras de un sistema, es facil confundir
los beneficios de una buena descomposición con una estructura 
jerárquica.
Tenemos una estructura jerárquica si ciertas relaciones pueden ser
definidas entre los módulos o programas, y la relación es un orden
parcial.

La existencia de una estructura jerárquica nos asegura que podemos
podar los niveles superiores del árbol y empezar uno nuevo.

Una estructura jerárquica y una buena descomposición son dos propiedades
deseables pero independientes.
